package br.com.seibzhen.specification;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

public class MethodNamesExtractor {

	private static final String BLANK_SPACE = "";
	private static final String JUNIT_TEST_PREFFIX_REGEX = "(t|T)est";
	private static final String JUNIT_TEST_PREFFIX = "test";
	
	/**
	 * Extracts a list of test method names from the supplied test class.
	 * Two criteria are used for determining method names; if there's a 'test' prefix to the
	 * test method name it is considered a junit3 method and whereas when a org.junit.Test annotation
	 * is present it is considered a junit one.
	 * <br/>
	 * Junit3 methods are stripped of their 'test' prefix.
	 * @param clazz the test class
	 * @return
	 */
	public List<String> extract(Class<?> clazz){
		
		if(clazz == null){
			throw new IllegalArgumentException("Class cannot be null!");
		}
		
		Method[] methods = clazz.getMethods();
		List<String> methodNames = new ArrayList<String>();
		
		for(Method method : methods){
			if(isAJunit3Method(method)){
				methodNames.add(replaceJunit3TestPrefix(method));
			}else if(isAJunit4Method(method)){
				methodNames.add(method.getName());
			}
		}
		
		return methodNames;
	}
	
	protected Boolean isAJunit3Method(Method method){
		return method.getName().toLowerCase().startsWith(JUNIT_TEST_PREFFIX);
	}
	
	protected Boolean isAJunit4Method(Method method){
		return method.isAnnotationPresent(Test.class);
	}
	
	protected String replaceJunit3TestPrefix(Method method){
		return method.getName().replaceFirst(JUNIT_TEST_PREFFIX_REGEX, BLANK_SPACE);
	}
}
